<?php
/**
 * @author Administrator
 * @date 2022/10/20 20:20
 * @desciption:JsonApi的中间件网关
 */

namespace JsonApi\Middleware;

use App\GraphQL\UserType;
use Closure;
use JsonApi\Fields;
use JsonApi\ObjectType;

class Gateway
{

    public function handle($request, Closure $next)
    {
        //todo JsonApi查询的网关：限制速率，注入字段，过滤字段（权限）==
        $this->injection($request);
        return $next($request);
    }

    /**
     * 注入字段
     * 1. 解析请求内容
     * 2. 根据请求内容，注入相对应的字段，并根据权限过滤字段
     */
    public function injection($request){
        //todo 
        $rawInput   = file_get_contents('php://input');
        $input      = json_decode($rawInput, true);
        $input      = $input["query"];
        $input      = substr($input,1,-2);
        $fields     = $this->extractFields($input);
        $this->registerFields($fields);
    }

    /**
     * @param array $fields
     * 注入字段
     */
    private function registerFields(array $fields){
        foreach($fields as $field){
            $class  = $this->getTypeClassName(ucfirst($field));
            if(class_exists($class) && method_exists($class,"bind")){
                Fields::set($class::bind());
            }
        }
    }

    private function getTypeClassName(string $field){
        return ObjectType::FIELDS_NAMESPACE . "\\" . $field . "Type";
    }

    /**
     * @param $input
     * @return array
     * 解析请求内容，提取第一层字段
     */
    private function extractFields($input){
        $s = strlen($input);
        if($s <= 0){
            return [];
        }
        $result = "";
        $limit  = [];
        for($i = 0; $i < $s; $i++){
            if( ($input[$i] === " " || $input[$i] === "\r" || $input[$i] === "\n") ||
                (!in_array($input[$i],["(",")","{","}"]) && !empty($limit))
            ){
                continue;
            }
            if($input[$i] === "(" || $input[$i] === "{"){
                array_push($limit,$input[$i]);
                continue;
            }
            if($input[$i] === ")" || $input[$i] === "}"){
                array_pop($limit);
                continue;
            }
            $result .= $input[$i];
        }
        if(!empty($result)){
            return explode(",",$result);
        }
        return [];
    }
}